home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MACD 5
/
MACD 5.bin
/
www
/
ludzie
/
txf
/
progs
/
anystrtolong.lha
/
AnyStrToLong
/
AnyLongToStr.asm
next >
Wrap
Assembly Source File
|
1980-01-04
|
5KB
|
252 lines
**********************************************************************
*
* AnyLongToStr - Convert 32-bit value to ASCII
*
* Input: d0 - the value to convert
* d1 - flags
* a0 - pointer to a buffer
* Output: d0 - number of characters written (or null for error)
* a0 - address of the terminating null
*
*
* Flags are:
* LTS_DECIMAL - normal decimal conversion
* LTS_SIGN_LONG - decimal signed mode (longword)
* LTS_SIGN_WORD - signed (word)
* LTS_SIGN_BYTE - signed (byte)
* LTS_BINARY - convert to binary
* LTS_HEX_UPPER - convert to hex (A-F)
* LTS_HEX_LOWER - convert to hex (a-f)
*
*
* You should pass a buffer with at least 11/12 (decimal/negative
* decimal), 9 (hex) or 33 (binary) bytes of space.
* If flags = #1, checks the 31 bit and if it is high, assumes
* the value is lower than 0.
* This string is null-terminated. Address of the terminating
* null is returned in a0. The null is included in number of chars
* written.
*
* When you specify decimal non-signed mode, then even if
* bit 31 is set you'll get value in range 0 to 4.294.967.295. In
* signed mode you'll get values in range from -2.147.483.647 to
* 2.147.483.648 (negative when bit 31/15/7 is set, depending on the
* choosen mode). Minus sign is written, if needed (and added to chars
* counter returned in d0).
*
* No prefix is written in hex/bin mode!!! If you need it, write
* it yourself. That's how you can choose between '$'/'0x' :-)
*
* Alters only scratch registers (d0, d1, a0, a1). Uses 12 bytes
* of stack.
*
*
* © 1996 by Tadek Knapik (tadek@student.uci.agh.edu.pl).
* Public Domain. E-mail appreciated :-)
*
**********************************************************************
LTS_DECIMAL equ 0
LTS_BINARY equ 2
LTS_HEX_UPPER equ 4
LTS_HEX_LOWER equ 8
LTS_SIGN_LONG equ 16
LTS_SIGN_WORD equ 32
LTS_SIGN_BYTE equ 64
LTS_NEGATIVE equ LTS_SIGN_LONG
LTS_HEX equ LTS_HEX_UPPER
AnyLongToStr:
movem.l d2-d4,-(sp)
moveq #0,d2 ;the counter
cmpi.l #LTS_DECIMAL,d1
beq LTSDecConvert
cmpi.l #LTS_SIGN_LONG,d1
beq LTSMinDecConvert
cmpi.l #LTS_SIGN_WORD,d1
beq LTSMinWDecConvert
cmpi.l #LTS_SIGN_BYTE,d1
beq LTSMinBDecConvert
cmpi.l #LTS_BINARY,d1
beq LTSBinConvert
move.l #'A',d2 ;ASCII base uppercased
cmpi.l #LTS_HEX_UPPER,d1
beq LTSHexConvert
move.l #'a',d2 ;ASCII base lowercased
cmpi.l #LTS_HEX_LOWER,d1
beq LTSHexConvert
LTSError:
movem.l (sp)+,d2-d4
moveq #0,d1
moveq #0,d0
rts
;--------------------
LTSMinBDecConvert:
ext.w d0 ;extend to word
LTSMinWDecConvert
ext.l d0 ;extend to longword
LTSMinDecConvert:
btst #31,d0
beq LTSDecConvert
move.b #'-',(a0)+ ;the minus sign
addq.l #1,d2
neg.l d0 ;so I need plus now
LTSDecConvert:
moveq #0,d1 ;zeroes flag
move.l #1000000000,d4 ;32-bit max power of 10
LTSDecAgain:
cmp.l d4,d0
bcc LTSDecMatch
tst.l d1 ;write zeroes?
beq LTSDecNextPass ;not yet
move.b #'0',(a0)+ ;write it
addq.l #1,d2 ;one character more
bra LTSDecNextPass
LTSDecMatch:
moveq #1,d1 ;means write zeros from now
moveq #0,d3 ;clear temporary
LTSDecLoop:
addq.l #1,d3 ;
sub.l d4,d0
bpl LTSDecLoop ;branch if not less than 0
add.l d4,d0 ;did it too many times
subq.l #1,d3 ;as well
addi.l #'0',d3 ;ASCII 0
move.b d3,(a0)+
addq.l #1,d2 ;the counter
LTSDecNextPass:
bsr LTSDecDivideByTen
tst.l d4
beq LTSError
cmpi.l #1,d4
bne LTSDecAgain
;less than 10 in d0..
addi.l #'0',d0
move.b d0,(a0)+
addq.l #1,d2
LTSDecOver:
move.b #0,(a0)
suba.l #1,a0
addq.l #1,d2 ;null is a character, too
move.l d2,d0
movem.l (sp)+,d2-d4
rts
LTSDecDivideByTen:
;
;if your proggy is to be run on 020+ only!
; But beware! It is one of instructions not present on 68060! And it
;will be significantly slower, because it is emulated in software then.
;
; divu.l #10,d4
; rts
;now 68000 part. Thanks for Simon N Goodwin for this routine!
moveq #0,d3 ;temporary register
swap d4 ;higher 16 bits
move.w d4,d3 ;
divu #10,d3 ;divide higher 16 bits
swap d3 ;store in high word of d3
move.w d3,d4 ;safe?
swap d4 ;
divu #10,d4 ;divide lower 16 bits
move.w d4,d3 ;
exg d3,d4 ;
rts
;--------------------
LTSHexConvert:
move.l #8,d4 ;8 characters
LTSHexLoop:
rol.l #4,d0 ;prepare next nybble
move.l d0,d1 ;spare
andi.l #$0000000F,d1 ;the nybble
move.l #'0',d3 ;ASCII base (for 0-9)
cmpi.l #9,d1 ;normal or a-f
ble LTSHexDec
move.l d2,d3 ;new base (A-F or a-f)
subi.l #$A,d1 ;new value :-)
LTSHexDec:
add.l d1,d3 ;add soup base, cover it and
move.b d3,(a0)+ ;wait for 3 minutes :-)
subq.l #1,d4 ;
bne LTSHexLoop
move.b #0,(a0) ;terminate
suba.l #1,a0 ;
movem.l (sp)+,d2-d4 ;give it back..
move.l #9,d0 ;no way for 8 :-)
rts
;--------------------
LTSBinConvert:
move.l #32,d4 ;8 characters
LTSBinLoop:
rol.l #1,d0 ;one bit
move.l d0,d1 ;spare
andi.l #$00000001,d1 ;the bit
move.l #'0',d3 ;ASCII base
add.l d1,d3 ;do it again
move.b d3,(a0)+ ;
subq.l #1,d4 ;
bne LTSBinLoop
move.b #0,(a0) ;terminate
suba.l #1,a0 ;
movem.l (sp)+,d2-d4 ;give it back..
move.l #33,d0 ;am I sure of that?
rts
**********************************************************************